package com.octopus.crontab;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

import com.octopus.string.StringUtils;


public class CrontabTimeMatcher {
	
	/*
	 * The Day of week is start from 1 to 7, that represents Sunday, Monday, Tuesday, Wednesday, Thursday, Saturday. 
	 */
	
	public static final String REGULAR_EXPRESS_CRONTABLIKE = "(\\*|[0-5][0-9]|((([0-5][0-9],)+[0-5][0-9]))) (\\*|([0-1][0-9]|[2][0-3])|((([0-1][0-9]|[2][0-3]),)+([0-1][0-9]|[2][0-3]))) (\\*|(([0-2][0-9])|([3][0-1]))|(((([0-2][0-9])|([3][0-1])),)+((([0-2][0-9])|([3][0-1]))))) (\\*|(0[1-9]|1[0-2])|(((0[1-9]|1[0-2]),)+(0[1-9]|1[0-2]))) (\\*|([1-7])|(([1-7],)+[1-7]))";
	
	private HashMap<String, String> MINUTES = new HashMap<String, String>();
	private HashMap<String, String> HOURS = new HashMap<String, String>();
	private HashMap<String, String> DAYS = new HashMap<String, String>();
	private HashMap<String, String> MONTHS = new HashMap<String, String>();
	private HashMap<String, String> DAYOFWEEKS = new HashMap<String, String>(); 
	
	public CrontabTimeMatcher(String crontabString) throws CrontabTimerNotMatchException{
		if(crontabString == null || !crontabString.matches(REGULAR_EXPRESS_CRONTABLIKE)){
			throw new CrontabTimerNotMatchException(StringUtils.concat(crontabString, " is not valid crontab timer String"));
		}else{
			String[] time = crontabString.split(" ");
			String minutes = time[0];
			String hours = time[1];
			String days = time[2];
			String months = time[3];
			String dayofweeks = time[4];
			String[] minutesUnits = minutes.split(",");
			String[] hoursUnits = hours.split(",");
			String[] daysUnits = days.split(",");
			String[] monthsUnits = months.split(",");
			String[] dayofweeksUnits = dayofweeks.split(",");
			for(String minute : minutesUnits){
				MINUTES.put(minute, minute);
			}
			for(String hour : hoursUnits){
				HOURS.put(hour, hour);
			}
			for(String day : daysUnits){
				DAYS.put(day, day);
			}
			for(String month : monthsUnits){
				MONTHS.put(month, month);
			}
			for(String dayofweek : dayofweeksUnits){
				DAYOFWEEKS.put(dayofweek, dayofweek);
			}
		}
	}
	
	public boolean timeMatch(Date date){
		if(date == null){
			return false;
		}else{
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			int minute = calendar.get(Calendar.MINUTE);
			int hour = calendar.get(Calendar.HOUR_OF_DAY);
			int day = calendar.get(Calendar.DAY_OF_MONTH);
			int month = (calendar.get(Calendar.MONTH)+1);
			int dayofweek = (calendar.get(Calendar.DAY_OF_WEEK));
			
			String s_minute = String.valueOf(minute);
			String s_hour = String.valueOf(hour);
			String s_day = String.valueOf(day);
			String s_month = String.valueOf(month);
			String s_dayofweek = String.valueOf(dayofweek);
			
			if(s_minute.length() == 1){
				s_minute = StringUtils.concat("0", s_minute);
			}
			if(s_hour.length() == 1){
				s_hour = StringUtils.concat("0", s_hour);
			}
			if(s_day.length() == 1){
				s_day = StringUtils.concat("0", s_day);
			}
			if(s_month.length() == 1){
				s_month = StringUtils.concat("0", s_month);
			}
			
			if(MINUTES.get("*") == null && MINUTES.get(s_minute) == null){
				return false;
			}
			
			if(HOURS.get("*") == null && HOURS.get(s_minute) == null){
				return false;
			}
			
			if(DAYS.get("*") == null && DAYS.get(s_day) == null){
				return false;
			}
			
			if(MONTHS.get("*") == null && MONTHS.get(s_month) == null){
				return false;
			}
			
			if(DAYOFWEEKS.get("*") == null && DAYOFWEEKS.get(s_dayofweek) == null){
				return false;
			}
			
			return true;
		}
	}
	
	public static void main(String args[]) throws CrontabTimerNotMatchException{
		CrontabTimer timer = new CrontabTimer("ttt", false);
		timer.addTask(new TestTask("36 * * * *"));
	}
}
